#include "ZipBrowser.h"
#include "../log/LoggerManager.h"

extern LoggerManager* g_logger;

ZipBrowser::ZipBrowser()
{
    this->zipTree = new ZipTree();
    g_logger->addLogger(new ConsoleLogger());
}

ZipTree* ZipBrowser::navigate(char* fileName)
{
    this->zipTree->clear();
    FILE* file = fopen(fileName, "rb"); //Open a zip file
    int header;
    short size;
    short flag = 0;
    short compressedMethod;
    short extraFieldLength = 0;
    int compressedSize = 0;
    int unCompressedSize;
    int count = 0;
    int crc;

    while (!feof(file) && flag != 10)
    {
	fseek(file, compressedSize + extraFieldLength, SEEK_CUR); //Skip the content of the file to read the next file
	fread(&header, sizeof (header), 1, file); // Read the header to know if is a file
	if (header == 0x04034b50) //To know if is a file header
	{
	    fseek(file, 2, SEEK_CUR); // Skip to the flag
	    fread(&flag, sizeof (flag), 1, file); // read the flag
	    fread(&compressedMethod, sizeof (compressedMethod), 1, file); //read the compression method
	    fseek(file, 4, SEEK_CUR); //Skip to the read the CRC-32
	    fread(&crc, sizeof (crc), 1, file); // read the CRC-32
	    fread(&compressedSize, sizeof (compressedSize), 1, file); //Read the compressed size
	    fread(&unCompressedSize, sizeof (unCompressedSize), 1, file); // Read the uncompressed size
	    fread(&size, sizeof (size), 1, file); // read the size of the file name
	    fread(&extraFieldLength, sizeof (extraFieldLength), 1, file); // read the size of the extra field

	    char name[size + 1];
	    fread(&name, sizeof (char), size, file); // Read the name of the file
	    name[size] = '\0';
	    count++;
	    INFO("File name: %s\nSize: %d\n", name, size);
	    INFO("CompresseSize: %d\nUncompressedSize: %d\n"
		    "Compressed Method: %d\n", compressedSize, unCompressedSize, compressedMethod);
	    INFO("Flag: %d\nCRC-32: %x\n", flag, crc);
	    printf("----------------------------------\n");
	    updateZipTree(name, crc);
	}
    }
    INFO("Exist %d files\n", count);
    return zipTree;
}

void ZipBrowser::updateZipTree(char* path, int crc)
{
    char* orig = new char[strlen(path) + 1];
    strcpy(orig, path);
    char* tmp = 0;
    char *ptrToken = 0;
    char*currentNode = new char[strlen(path) + 1];
    ptrToken = strtok(path, "/");
    ptrToken[strlen(ptrToken)] = '\0';
    zipTree->add(new DirectoryNode(ptrToken));
    strcpy(currentNode, ptrToken);
    while (ptrToken != NULL)
    {
	ptrToken = strtok(NULL, "/");
	if (ptrToken != NULL)
	{
	    tmp = new char[strlen(currentNode) + 1];
	    tmp[strlen(currentNode)] = '\0';
	    strcpy(tmp, currentNode);
	    strcat(currentNode, "/");
	    strcat(currentNode, ptrToken);
	    if (currentNode && tmp)
            {
		if (strcmp(currentNode, orig) == 0 && crc != 0)
		    zipTree->addToNode(currentNode, false, tmp);
		else
		    zipTree->addToNode(currentNode, true, tmp);
 	    }
         }
    }
}
